/* OSM layers for gvSIG. 
 * Geographic Information System of the Valencian Government
*
* Copyright (C) 2012 Nacho Brodin
* 
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
* MA  02110-1301, USA.
* 
*/
package org.gvsig.raster.osm.io;

import java.awt.geom.AffineTransform;

import org.cresques.cts.IProjection;
import org.gvsig.fmap.crs.CRSFactory;
import org.gvsig.fmap.dal.DALLocator;
import org.gvsig.fmap.dal.DataStore;
import org.gvsig.fmap.dal.coverage.dataset.Buffer;
import org.gvsig.fmap.dal.coverage.datastruct.BandList;
import org.gvsig.fmap.dal.coverage.datastruct.Extent;
import org.gvsig.fmap.dal.coverage.exception.BandAccessException;
import org.gvsig.fmap.dal.coverage.exception.FileNotOpenException;
import org.gvsig.fmap.dal.coverage.exception.InvalidSetViewException;
import org.gvsig.fmap.dal.coverage.exception.NotSupportedExtensionException;
import org.gvsig.fmap.dal.coverage.exception.ProcessInterruptedException;
import org.gvsig.fmap.dal.coverage.exception.RasterDriverException;
import org.gvsig.fmap.dal.coverage.store.props.ColorInterpretation;
import org.gvsig.fmap.dal.exception.OpenException;
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
import org.gvsig.metadata.MetadataLocator;
import org.gvsig.raster.cache.tile.provider.TileListener;
import org.gvsig.raster.cache.tile.provider.TileServer;
import org.gvsig.raster.impl.datastruct.ExtentImpl;
import org.gvsig.raster.impl.provider.DefaultRasterProvider;
import org.gvsig.raster.impl.provider.RasterProvider;
import org.gvsig.raster.impl.store.DefaultStoreFactory;
import org.gvsig.raster.impl.store.properties.DataStoreColorInterpretation;
import org.gvsig.raster.impl.store.properties.DataStoreTransparency;
import org.gvsig.raster.osm.cachestruct.OSMCacheStruct;
import org.gvsig.raster.osm.downloader.OSMTileServer;
import org.gvsig.tools.ToolsLocator;
import org.gvsig.tools.task.TaskStatus;
/**
 * Data provider for OSM servers
 *
 * @author Nacho Brodin (nachobrodin@gmail.com)
 */
public class OSMProvider extends DefaultRasterProvider {
	public static String                     NAME                     = "OSM Raster";
	public static String                     DESCRIPTION              = "OSM Raster Server";
	public final String                      METADATA_DEFINITION_NAME = NAME;
	private Extent                           viewRequest              = null;
	private TileServer                       tileServer               = null;
	private boolean                          open                     = false;
    private DataStoreTransparency            fileTransparency         = null;
    //private static final Logger              logger                   = LoggerFactory.getLogger(OSMProvider.class);
    
	public static void register() {
		DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator.getDataManager();
		
		if (dataman != null && !dataman.getStoreProviders().contains(NAME)) {
			dataman.registerStoreProvider(NAME,
					OSMProvider.class, OSMDataParametersImpl.class);
		}
		
		dataman.registerStoreFactory(NAME, DefaultStoreFactory.class);
	}
	
	public OSMProvider() {
	}
	
	/**
	 * Opens the dataset.
	 * @param proj Projection
	 * @param fName File name
	 * @throws NotSupportedExtensionException
	 */
	public OSMProvider(String params) throws NotSupportedExtensionException, OpenException {
		super(params);
		
	}
	
	public OSMProvider (OSMDataParametersImpl params,
			DataStoreProviderServices storeServices) throws NotSupportedExtensionException, OpenException {
		super(params, storeServices, ToolsLocator.getDynObjectManager()
				.createDynObject(
						MetadataLocator.getMetadataManager().getDefinition(
								DataStore.METADATA_DEFINITION_NAME)));
		init(params, storeServices);
	}

	/**
	 * Build file references
	 * @param proj Projection
	 * @param param Load parameters
	 * @throws NotSupportedExtensionException
	 */
	public void init (OSMDataParametersImpl params,
			DataStoreProviderServices storeServices) throws NotSupportedExtensionException, OpenException {
		setParam(storeServices, params);
		setDataType(new int[]{Buffer.TYPE_BYTE, Buffer.TYPE_BYTE, Buffer.TYPE_BYTE, Buffer.TYPE_BYTE});
		bandCount = 4;
		super.init();
		fileSize = (long)(getWidth() * getHeight() * 3);
		open = true;
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getProjection()
	 */
	public IProjection getProjection() {
		if(proj == null)
			proj = CRSFactory.getCRS("EPSG:900913");
		return proj;
	}
	
	/**
	 * Gets the bounding box in world coordinates. 
	 * @return Extent
	 */
	public Extent getExtent() {
		return ((OSMCacheStruct)getTileServer().getStruct()).getWorldExtent();
	}
	
	/**
	 * Reloads metadata using the selected grid
	 */
	@SuppressWarnings("unused")
	private void reloadMetadataFromGrid() {
		//wktProjection = null;
		//CrsWkt crs = new CrsWkt(wktProjection);
		//IProjection proj = CRSFactory.getCRS("EPSG:23030");
		
		/*ownTransformation = new AffineTransform(
				scaleX, 0, 
				0, -scaleY, 
				pRect.getMinX(), 
				pRect.getMaxY());*/
		externalTransformation = (AffineTransform)ownTransformation.clone();
		bandCount = 3; 
		setDataType(new int[]{Buffer.TYPE_BYTE, Buffer.TYPE_BYTE, Buffer.TYPE_BYTE});
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#load()
	 */
	public RasterProvider load() {
		return this;
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.RasterProvider#isOpen()
	 */
	public boolean isOpen() {
		return open;
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#close()
	 */
	public void close() {
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#translateFileName(java.lang.String)
	 */
	public String translateFileName(String fileName) {
		return fileName;
	}

	/**
	 * Asigna el extent de la vista actual. existe un fichero .rmf debemos hacer una transformaci�n
	 * de la vista asignada ya que la petici�n viene en coordenadas del fichero .rmf y la vista (v)
	 * ha de estar en coordenadas del fichero.
	 */
	public void setView(Extent e) {
		viewRequest = new ExtentImpl(e);
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getView()
	 */
	public Extent getView() {
		return viewRequest;
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getWidth()
	 */
	public double getWidth() {
		int n = getTileServer().getStruct().getNumberOfLevels() - 1;
		return getExtent().width() / getTileServer().getStruct().getPixelSizeByLevel(n);
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getHeight()
	 */
	public double getHeight() {
		int n = getTileServer().getStruct().getNumberOfLevels() - 1;
		return getExtent().width() / getTileServer().getStruct().getPixelSizeByLevel(n);
	}

	/*
	 *  (non-Javadoc)
	 * @see org.gvsig.raster.dataset.RasterDataset#readBlock(int, int)
	 */
	public Object readBlock(int pos, int blockHeight, double scale)
		throws InvalidSetViewException, FileNotOpenException, RasterDriverException, ProcessInterruptedException {
		return null;
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getData(int, int, int)
	 */
	public Object getData(int x, int y, int band)throws InvalidSetViewException, FileNotOpenException, RasterDriverException {
		return null;
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getBlockSize()
	 */
	public int getBlockSize(){
		return 0;
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getTransparency()
	 */
	public DataStoreTransparency getTransparency() {
		if(fileTransparency == null)
			fileTransparency = new DataStoreTransparency();
		return fileTransparency;
	}

	/**
	 * Informa de si el driver ha supersampleado en el �ltimo dibujado. Es el driver el que colocar�
	 * el valor de esta variable cada vez que dibuja.
	 * @return true si se ha supersampleado y false si no se ha hecho.
	 */
	public boolean isSupersampling() {
		return false;
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#setAffineTransform(java.awt.geom.AffineTransform)
	 */
	public void setAffineTransform(AffineTransform t){
		super.setAffineTransform(t);
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.RasterProvider#getOverviewCount(int)
	 */
	public int getOverviewCount(int band) throws BandAccessException, RasterDriverException {
		if(band >= getBandCount())
			throw new BandAccessException("Wrong band");
		return 0;
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getOverviewWidth(int, int)
	 */
	public int getOverviewWidth(int band, int overview) throws BandAccessException, RasterDriverException {
		if (band >= getBandCount())
			throw new BandAccessException("Wrong band");
		return 0;
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#getOverviewHeight(int, int)
	 */
	public int getOverviewHeight(int band, int overview) throws BandAccessException, RasterDriverException {
		if (band >= getBandCount())
			throw new BandAccessException("Wrong band");
		return 0;
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#isOverviewsSupported()
	 */
	public boolean isOverviewsSupported() {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.DefaultRasterProvider#isReproyectable()
	 */
	public boolean isReproyectable() {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * @see org.gvsig.fmap.dal.spi.DataStoreProvider#getName()
	 */
	public String getName() {
		return NAME;
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.dataset.RasterProvider#getColorInterpretation()
	 */
	public ColorInterpretation getColorInterpretation() {
		if(super.getColorInterpretation() == null) {
			super.setColorInterpretation(DataStoreColorInterpretation.createRGBInterpretation());
		}
		return super.getColorInterpretation();
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.RasterProvider#setStatus(org.gvsig.raster.impl.provider.RasterProvider)
	 */
	public void setStatus(RasterProvider provider) {
		if(provider instanceof OSMProvider) {
			//Not implemented yet
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.RasterProvider#isTimeSupported()
	 */
	public boolean isTimeSupported() {
		return true;
	}
	
	/*
	 * (non-Javadoc)
	 * @see org.gvsig.raster.impl.provider.RasterProvider#getTileServer()
	 */
	public TileServer getTileServer() {
		if(tileServer == null)
			tileServer = new OSMTileServer(this, 
					((OSMDataParameters)param).getTileSuffix(), 
					((OSMDataParameters)param).getNumberOfLevels());
		return tileServer;
	}

	@Override
	protected void getWindow(Extent ex, int bufWidth, int bufHeight,
			BandList bandList, TileListener listener, TaskStatus taskStatus)
			throws ProcessInterruptedException, RasterDriverException {
		
	}

	@Override
	protected Buffer getWindow(Extent extent, BandList bandList,
			Buffer rasterBuf, TaskStatus status)
			throws ProcessInterruptedException, RasterDriverException {
		return null;
	}

	@Override
	protected Buffer getWindow(double x, double y, double w, double h,
			BandList bandList, Buffer rasterBuf, boolean adjustToExtent,
			TaskStatus status) throws ProcessInterruptedException,
			RasterDriverException {
		return null;
	}

	@Override
	protected Buffer getWindow(Extent extent, int bufWidth, int bufHeight,
			BandList bandList, Buffer rasterBuf, boolean adjustToExtent,
			TaskStatus status) throws ProcessInterruptedException,
			RasterDriverException {
		return null;
	}

	@Override
	protected Buffer getWindow(int x, int y, int w, int h, BandList bandList,
			Buffer rasterBuf, TaskStatus status)
			throws ProcessInterruptedException, RasterDriverException {
		return null;
	}
}